/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.unal.behaviours;

import co.edu.unal.agentes.BookDistributorAgent;
import co.edu.unal.agentes.BookSellerAgent;
import jade.core.AID;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import javax.swing.JTextArea;

/**
 *
 * @author raider
 */
public class RequestPerformer extends Behaviour {

    private AID bestSeller; // The agent who provides the best offer
    private int bestPrice; // The best offered price
    private int repliesCnt = 0; // The counter of replies from seller agents
    private MessageTemplate mt; // The template to receive replies
    private int step = 0;
    private AID[] sellerAgents;
    private String targetBookData;
    JTextArea log;

    public RequestPerformer(AID[] sellerAgents, String targetBookTitle, String quantity, JTextArea log) {
        this.sellerAgents = sellerAgents;
        this.targetBookData = targetBookTitle+","+quantity;
        this.log = log;
    }

    @Override
    public void action() {
        switch (step) {
            case 0:
                // Send the cfp to all sellers
                ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
                for (int i = 0; i < sellerAgents.length; ++i) {
                    cfp.addReceiver(sellerAgents[i]);
                }
                cfp.setContent(targetBookData);
                cfp.setConversationId("book - trade");
                cfp.setReplyWith("cfp"+System.currentTimeMillis()); // Unique value
                myAgent.send(cfp);
                // Prepare the template to get proposals
                mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book - trade"),MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
                step++;
                break;
            case 1:
                // Receive all proposals/refusals from seller agents
                ACLMessage reply = myAgent.receive(mt);
                if (reply != null) {
                // Reply received
                    if (reply.getPerformative() == ACLMessage.PROPOSE) {
                    // This is an offer
                        int price = Integer.parseInt(reply.getContent());
                        if (bestSeller == null || price < bestPrice) {
                    // This is the best offer at present
                            bestPrice = price;
                            bestSeller = reply.getSender();
                        }
                    }else if (reply.getPerformative() == ACLMessage.REFUSE) {
                        log.setText(log.getText()+ "\n" + reply.getSender().getLocalName()+": "+reply.getContent());
                        System.out.println(reply.getSender().getLocalName()+": "+reply.getContent());
                    }
                    repliesCnt++;
                    if (repliesCnt >= sellerAgents.length) {
                    // We received all replies
                        step++;
                    }
                } else {
                    block();
                }
                break;
            case 2:
                // Send the purchase order to the seller that provided the best offer
                ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
                order.addReceiver(bestSeller);
                order.setContent(targetBookData);
                order.setConversationId("book - trade");
                order.setReplyWith("order"+System.currentTimeMillis());
                myAgent.send(order);
                // Prepare the template to get the purchase order reply
                mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book - trade"),MessageTemplate.MatchInReplyTo(order.getReplyWith()));
                step++;
                break;
            case 3:
                // Receive the purchase order reply
                reply = myAgent.receive(mt);
                if (reply != null) {
                // Purchase order reply received
                    if (reply.getPerformative() == ACLMessage.INFORM) {
                        // Purchase successful. We can terminate
                        String[] datos = targetBookData.split(",");
                        if (myAgent instanceof BookSellerAgent) {
                            BookSellerAgent seller = (BookSellerAgent) myAgent;
                            seller.updateCatalogue(datos[0], bestPrice);
                        } else if (myAgent instanceof BookDistributorAgent) {
                            BookDistributorAgent distributor = (BookDistributorAgent) myAgent;
                            distributor.updateCatalogue(datos[0], bestPrice);
                        }
                        log.setText(log.getText()+ "\n" +myAgent.getLocalName()+": "+" \"" +datos[0]+"\". "+datos[1]+" unit(s) successfully purchased. Price (per unit) = "+bestPrice+" to "+reply.getSender().getLocalName());
                        System.out.println(myAgent.getLocalName()+": "+" \"" +datos[0]+"\". "+datos[1]+" unit(s) successfully purchased. Price (per unit) = "+bestPrice+" to "+reply.getSender().getLocalName());
                    }
                    step++;
                } else {
                    block();
                }
                break;
        }
    }

    @Override
    public boolean done() {
        return ((step == 2 && bestSeller == null) || step == 4);
    }
}